import 'dart:typed_data';

/// 隧道请求模型
class TunnelRequest {
  final String localPort;
  final String localHost;
  final String serverName;

  TunnelRequest({
    required this.localPort,
    required this.localHost,
    required this.serverName,
  });

  Map<String, dynamic> toJson() {
    return {
      'localPort': localPort,
      'localHost': localHost,
      'serverName': serverName,
    };
  }
}

/// 隧道响应模型
class TunnelResponse {
  final String tunnelId;
  final String tunnelHost;
  final String tunnelPort;
  final String publicPort;

  TunnelResponse({
    required this.tunnelId,
    required this.tunnelHost,
    required this.tunnelPort,
    required this.publicPort,
  });

  factory TunnelResponse.fromJson(Map<String, dynamic> json) {
    return TunnelResponse(
      tunnelId: json['tunnelId']?.toString() ?? '',
      tunnelHost: json['tunnelHost']?.toString() ?? '',
      tunnelPort: json['tunnelPort']?.toString() ?? '',
      publicPort: json['publicPort']?.toString() ?? '',
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'tunnelId': tunnelId,
      'tunnelHost': tunnelHost,
      'tunnelPort': tunnelPort,
      'publicPort': publicPort,
    };
  }
}

/// 隧道数据模型（完整信息）
class TunnelData {
  final String id;
  final String localHost;
  final String localPort;
  final String serverName;
  final String tunnelHost;
  final String tunnelPort;
  final String publicPort;
  final DateTime createdAt;
  final bool isConnected;
  final String? publicUrl;
  final String? tunnelType;

  TunnelData({
    required this.id,
    required this.localHost,
    required this.localPort,
    required this.serverName,
    required this.tunnelHost,
    required this.tunnelPort,
    required this.publicPort,
    required this.createdAt,
    required this.isConnected,
    this.publicUrl,
    this.tunnelType,
  });

  factory TunnelData.fromJson(Map<String, dynamic> json) {
    return TunnelData(
      id: json['id']?.toString() ?? '',
      localHost: json['localHost']?.toString() ?? '',
      localPort: json['localPort']?.toString() ?? '',
      serverName: json['serverName']?.toString() ?? '',
      tunnelHost: json['tunnelHost']?.toString() ?? '',
      tunnelPort: json['tunnelPort']?.toString() ?? '',
      publicPort: json['publicPort']?.toString() ?? '',
      createdAt: DateTime.tryParse(json['createdAt']?.toString() ?? '') ?? DateTime.now(),
      isConnected: json['isConnected'] as bool? ?? false,
      publicUrl: json['public_url']?.toString(),
      tunnelType: json['tunnel_type']?.toString(),
    );
  }

  /// 从TunnelResponse创建TunnelData
  factory TunnelData.fromResponse(TunnelResponse response, {
    required String localHost,
    required String localPort,
    required String serverName,
  }) {
    return TunnelData(
      id: response.tunnelId,
      localHost: localHost,
      localPort: localPort,
      serverName: serverName,
      tunnelHost: response.tunnelHost,
      tunnelPort: response.tunnelPort,
      publicPort: response.publicPort,
      createdAt: DateTime.now(),
      isConnected: false,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'localHost': localHost,
      'localPort': localPort,
      'serverName': serverName,
      'tunnelHost': tunnelHost,
      'tunnelPort': tunnelPort,
      'publicPort': publicPort,
      'createdAt': createdAt.toIso8601String(),
      'isConnected': isConnected,
      'public_url': publicUrl,
      'tunnel_type': tunnelType,
    };
  }

  /// 获取隧道ID（用于连接）
  String get tunnelId => id;

  /// 获取本地服务地址
  String get localAddress => '$localHost:$localPort';

  /// 获取隧道服务器地址
  String get tunnelAddress => '$tunnelHost:$tunnelPort';

  /// 获取公共访问地址
  String get publicAddress => publicUrl ?? 'http://localhost:$publicPort';

  @override
  String toString() {
    return 'TunnelData{id: $id, serverName: $serverName, localAddress: $localAddress, publicAddress: $publicAddress, isConnected: $isConnected}';
  }
}

/// HTTP请求包模型（用于隧道传输）
class RequestPacket {
  final String type;
  final String requestId;
  final String method;
  final String path;
  final Map<String, List<String>> headers;
  final Uint8List body;

  RequestPacket({
    required this.type,
    required this.requestId,
    required this.method,
    required this.path,
    required this.headers,
    required this.body,
  });

  factory RequestPacket.fromJson(Map<String, dynamic> json) {
    final headers = <String, List<String>>{};
    final headersJson = json['headers'] as Map<String, dynamic>?;
    if (headersJson != null) {
      headersJson.forEach((key, value) {
        if (value is List) {
          headers[key] = value.cast<String>();
        } else {
          headers[key] = [value.toString()];
        }
      });
    }

    Uint8List body = Uint8List(0);
    if (json['body'] != null) {
      if (json['body'] is String) {
        body = Uint8List.fromList(json['body'].toString().codeUnits);
      } else if (json['body'] is List) {
        body = Uint8List.fromList((json['body'] as List).cast<int>());
      }
    }

    return RequestPacket(
      type: json['type']?.toString() ?? '',
      requestId: json['requestId']?.toString() ?? '',
      method: json['method']?.toString() ?? '',
      path: json['path']?.toString() ?? '',
      headers: headers,
      body: body,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'type': type,
      'requestId': requestId,
      'method': method,
      'path': path,
      'headers': headers,
      'body': body.toList(),
    };
  }
}

/// HTTP响应包模型（用于隧道传输）
class ResponsePacket {
  final String type;
  final String requestId;
  final int status;
  final Map<String, List<String>> headers;
  final Uint8List body;

  ResponsePacket({
    required this.type,
    required this.requestId,
    required this.status,
    required this.headers,
    required this.body,
  });

  factory ResponsePacket.fromJson(Map<String, dynamic> json) {
    final headers = <String, List<String>>{};
    final headersJson = json['headers'] as Map<String, dynamic>?;
    if (headersJson != null) {
      headersJson.forEach((key, value) {
        if (value is List) {
          headers[key] = value.cast<String>();
        } else {
          headers[key] = [value.toString()];
        }
      });
    }

    Uint8List body = Uint8List(0);
    if (json['body'] != null) {
      if (json['body'] is String) {
        body = Uint8List.fromList(json['body'].toString().codeUnits);
      } else if (json['body'] is List) {
        body = Uint8List.fromList((json['body'] as List).cast<int>());
      }
    }

    return ResponsePacket(
      type: json['type']?.toString() ?? 'response',
      requestId: json['requestId']?.toString() ?? '',
      status: (json['status'] as num?)?.toInt() ?? 200,
      headers: headers,
      body: body,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'type': type,
      'requestId': requestId,
      'status': status,
      'headers': headers,
      'body': body.toList(),
    };
  }
}

/// 隧道连接状态枚举
enum TunnelConnectionStatus {
  disconnected,
  connecting,
  connected,
  reconnecting,
  error,
}

/// 隧道连接状态模型
class TunnelConnectionState {
  final TunnelData tunnel;
  final TunnelConnectionStatus status;
  final String? errorMessage;
  final DateTime lastUpdate;

  TunnelConnectionState({
    required this.tunnel,
    required this.status,
    this.errorMessage,
    DateTime? lastUpdate,
  }) : lastUpdate = lastUpdate ?? DateTime.now();

  TunnelConnectionState copyWith({
    TunnelData? tunnel,
    TunnelConnectionStatus? status,
    String? errorMessage,
    DateTime? lastUpdate,
  }) {
    return TunnelConnectionState(
      tunnel: tunnel ?? this.tunnel,
      status: status ?? this.status,
      errorMessage: errorMessage ?? this.errorMessage,
      lastUpdate: lastUpdate ?? DateTime.now(),
    );
  }

  bool get isConnected => status == TunnelConnectionStatus.connected;
  bool get isConnecting => status == TunnelConnectionStatus.connecting;
  bool get hasError => status == TunnelConnectionStatus.error;

  @override
  String toString() {
    return 'TunnelConnectionState{tunnel: ${tunnel.id}, status: $status, error: $errorMessage}';
  }
}

